import 'dart:io';
import 'dart:math';
import 'dart:typed_data';

import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter_scaffold_plugin/utils/dialog/dialog_info.dart';
import 'package:flutter_scaffold_plugin/utils/dialog/dialog_manager.dart';
import 'package:flutter_scaffold_plugin/utils/flutter_draw/controllers/drawables/background/image_background_drawable.dart';
import 'package:flutter_scaffold_plugin/utils/flutter_draw/controllers/helpers/painter_controller_helper.dart';
import 'package:flutter_scaffold_plugin/utils/flutter_draw/controllers/painter_controller.dart';
import 'package:flutter_scaffold_plugin/utils/flutter_draw/controllers/settings/painter_settings.dart';
import 'package:flutter_scaffold_plugin/utils/flutter_draw/controllers/settings/text_settings.dart';
import 'package:flutter_scaffold_plugin/utils/flutter_draw/views/widgets/flutter_painter.dart';
import 'package:flutter_scaffold_plugin/utils/flutter_draw/controllers/extensions/ui_image_png_uint8list_getter_extension.dart';
import 'package:flutter_scaffold_plugin/utils/toast/toast_manager.dart';

import 'dart:ui' as ui;
import 'package:permission_handler_platform_interface/permission_handler_platform_interface.dart';

import 'package:flutter/cupertino.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter_scaffold_plugin/base/base.dart';
import 'package:flutter_scaffold_plugin/base/base_page.dart';
import 'package:flutter_scaffold_plugin/components/button.dart';
import 'package:flutter_scaffold_plugin/components/gesture_avoid_detector.dart';
import 'package:flutter_scaffold_plugin/components/navigation_bar.dart';
import 'package:flutter_scaffold_plugin/pages/teacher/teacher_living_page.dart';
import 'package:image_gallery_saver/image_gallery_saver.dart';
import 'package:path_provider/path_provider.dart';
import 'package:photo_manager/photo_manager.dart';
import 'package:popover/popover.dart';
import 'package:random_string/random_string.dart';

class TeacherExplainController extends TemplateController {
  String get imageUrl {
    return Get.find<TeacherLivingController>().imageUrl;
  }

  CachedNetworkImageProvider? imageProvider;

  final _minScale = 0.0.obs;
  get minScale => this._minScale.value;
  set minScale(value) => this._minScale.value = value;

  final _maxScale = 0.0.obs;
  get maxScale => this._maxScale.value;
  set maxScale(value) => this._maxScale.value = value;

  final _initialScale = 0.0.obs;
  get initialScale => this._initialScale.value;
  set initialScale(value) => this._initialScale.value = value;

  final _showPaint = false.obs;
  get showPaint => this._showPaint.value;
  set showPaint(value) {
    this._showPaint.value = value;
  }

  final _paintToolFold = false.obs;
  get paintToolFold => this._paintToolFold.value;
  set paintToolFold(value) => this._paintToolFold.value = value;

  final _enablePencil = false.obs;
  get enablePencil => this._enablePencil.value;
  set enablePencil(value) {
    this.paintController.freeStyleSettings =
        this.paintController.freeStyleSettings.copyWith(enabled: value);
    this._enablePencil.value = value;
  }

  final _enableText = false.obs;
  get enableText => this._enableText.value;
  set enableText(value) => this._enableText.value = value;

  final _strokeWidth = 5.0.obs;
  get strokeWidth => this._strokeWidth.value;
  set strokeWidth(value) {
    this.paintController.freeStyleSettings =
        this.paintController.freeStyleSettings.copyWith(strokeWidth: value);
    this._strokeWidth.value = value;
  }

  final _strokeColor = Colors.black.obs;
  get strokeColor => this._strokeColor.value;
  set strokeColor(value) {
    this.paintController.freeStyleSettings =
        this.paintController.freeStyleSettings.copyWith(color: value);
    this._strokeColor.value = value;
  }

  final _textFontSize = 17.0.obs;
  get textFontSize => this._textFontSize.value;
  set textFontSize(value) {
    this.paintController.textSettings = this
        .paintController
        .textSettings
        .copyWith(
            textStyle: this
                .paintController
                .textSettings
                .textStyle
                .copyWith(fontSize: value));
    this._textFontSize.value = value;
  }

  final _textColor = Colors.black.obs;
  get textColor => this._textColor.value;
  set textColor(value) {
    this.paintController.textSettings = this
        .paintController
        .textSettings
        .copyWith(
            textStyle: this
                .paintController
                .textSettings
                .textStyle
                .copyWith(color: value));
    this._textColor.value = value;
  }

  final List<double> strokWidths = [5.0, 10.0, 15.0, 20.0, 25.0];
  final List<double> pencileSizes = [16, 22, 28, 34, 40];

  final List<Color> paintColors = [
    Colors.black,
    Colors.grey,
    Colors.red,
    Colors.amber.shade800,
    Colors.yellow.shade700,
    Colors.green,
    Colors.green.shade200,
    Colors.blue,
    Colors.purple,
  ];

  // Paint
  PainterController? paintController;
  FocusNode textFocusNode = FocusNode();
  ui.Image? backgroundImage;
  Size imageInitialSize = ui.Size(0, 0);

  var rng = new Random();

  bool selectingPenThickness = false;
  bool selectingEraserThickness = false;
  double penThickness = 5.0;
  double eraserThickness = 5.0;

  ByteData? imagePngBytes;
  String? fileName;

  @override
  void onInit() {
    super.onInit();
    this.imageProvider = CachedNetworkImageProvider(this.imageUrl);
    paintController = PainterController(
      settings: PainterSettings(
        text: TextSettings(
          focusNode: textFocusNode,
          textStyle: TextStyle(
            fontWeight: FontWeight.bold,
            color: Colors.white,
            fontSize: 18,
          ),
        ),
        freeStyle: FreeStyleSettings(
          enabled: false,
          color: Colors.white,
          strokeWidth: 5,
        ),
      ),
    );
    _downloadImage();
  }

  _downloadImage() {
    final ImageStream stream = this.imageProvider!.resolve(
          const ImageConfiguration(),
        );
    stream.addListener(_getOrCreateListener());
  }

  Future<void> takeScreenshotAndSave(Future<Uint8List> data) async {
    Uint8List pngBytes = await data;
    final directory = (await getApplicationDocumentsDirectory()).path;
    String imageName = randomAlphaNumeric(200);
    fileName = imageName;
    File imgFile = File('$directory/${rng.nextInt(200)}.png');
    await ImageGallerySaver.saveImage(Uint8List.fromList(pngBytes));
    imgFile.writeAsBytes(pngBytes);
  }

  Future<bool> _askPermission() async {
    if (Platform.isIOS) {
      final result = await PermissionHandlerPlatform.instance
          .requestPermissions([Permission.photos]);
      return result[Permission.photos] == PermissionStatus.granted;
    } else {
      final result = await PermissionHandlerPlatform.instance
          .requestPermissions([Permission.storage]);
      return result[Permission.storage] == PermissionStatus.granted;
    }
  }

  ImageStreamListener _getOrCreateListener() {
    void handleImageFrame(ImageInfo info, bool synchronousCall) {
      final imageSize = Size(
        info.image.width.toDouble(),
        info.image.height.toDouble(),
      );
      double screenWidth = Get.size.width;
      this.initialScale = this.minScale = screenWidth / imageSize.width;
      this.maxScale = this.initialScale * 5;
      double height = imageSize.height * this.initialScale;
      this.imageInitialSize = ui.Size(screenWidth, height);

      this.backgroundImage = info.image;
      this.paintController!.background = info.image.backgroundDrawable;
    }

    final _imageStreamListener = ImageStreamListener(
      handleImageFrame,
    );
    return _imageStreamListener;
  }

  void removeLastDrawable() {
    this.paintController!.removeLastDrawable();
  }

  void addText() {
    if (this.paintController.freeStyleSettings.enabled)
      this.enablePencil = false;
    this.paintController!.addText();
  }

  void renderAndDisplayImage(context) {
    if (backgroundImage == null) return;
    final backgroundImageSize = Size(
        backgroundImage!.width.toDouble(), backgroundImage!.height.toDouble());

    // Render the image
    // Returns a [ui.Image] object, convert to to byte data and then to Uint8List
    final imageFuture = this
        .paintController!
        .renderImage(backgroundImageSize)
        .then<Uint8List>((ui.Image image) => image.pngBytes);
    Get.dialog(
      RenderedImageDialog(
        imageFuture: imageFuture,
        saveAction: () async {
          final granted = await this._askPermission();
          if (granted) {
            await this.takeScreenshotAndSave(imageFuture);
            ToastManager.showToast(msg: "保存成功");
            Get.back();
          } else {
            ToastManager.showToast(msg: "相册未授权");
          }
        },
      ),
    );
  }
}

class RenderedImageDialog extends StatelessWidget {
  final Future<Uint8List>? imageFuture;
  final ui.VoidCallback? saveAction;

  const RenderedImageDialog(
      {Key? key, @required this.imageFuture, this.saveAction})
      : super(key: key);

  @override
  Widget build(BuildContext context) {
    return AlertDialog(
      title: Text("预览"),
      content: FutureBuilder<Uint8List>(
        future: imageFuture,
        builder: (context, snapshot) {
          if (snapshot.connectionState != ConnectionState.done)
            return SizedBox(
              height: 50,
              child: Center(child: CircularProgressIndicator.adaptive()),
            );
          if (!snapshot.hasData || snapshot.data == null) return SizedBox();
          return InteractiveViewer(
              maxScale: 10, child: Image.memory(snapshot.data!));
        },
      ),
      actions: [
        CLTextButton(
          title: "保存",
          fontColor: Colors.black,
          onPressed: this.saveAction,
        )
      ],
    );
  }
}

// ,
class TeacherExpainPage extends TemplatePage<TeacherExplainController> {
  @override
  Widget buildBody(BuildContext context) {
    return Stack(
      children: [
        Container(
          color: Colors.black,
          child: Center(
            child: Hero(
              tag: "expain_image",
              child: this.paintScreen(),
            ),
          ),
        ),
        Align(
          alignment: Alignment.topCenter,
          child: GestureAvoidDetector(
            onTap: () {},
            child: Container(
              child: Obx(
                () => NavigationBar.customBar(
                  foregroundColor: Colors.white,
                  backgroundColor: Color.fromARGB(80, 0, 0, 0),
                  leftWidgets: this.navigationBarLeftActions(),
                  rightWidgets: this.navigationBarRightActions(),
                ),
              ),
            ),
          ),
        ),
        Align(
          alignment: Alignment.bottomRight,
          child: Obx(() {
            List<Widget> actions = [
              Container(
                padding: EdgeInsets.all(10),
                height: 60,
                width: 60,
                child: GestureAvoidDetector(
                  onTap: () {
                    bool fold = !this.controller.paintToolFold;
                    this.controller.paintToolFold = fold;
                  },
                  child: Column(
                    mainAxisAlignment: MainAxisAlignment.spaceBetween,
                    children: [
                      Icon(
                        CupertinoIcons.clear_thick,
                        color: Colors.white,
                      ),
                      Text(
                        "折叠",
                        style: TextStyle(
                          color: Colors.white,
                          fontSize: 10,
                        ),
                      ),
                    ],
                  ),
                ),
              ),
            ];
            if (!this.controller.paintToolFold) {
              actions.addAll([
                Container(
                  padding: EdgeInsets.all(10),
                  height: 60,
                  width: 60,
                  child: PopoverButton(
                    onPress: (context) {
                      this.controller.enableText = false;
                      this.controller.enablePencil = true;
                      this.showFreeStylePanel(context);
                    },
                    builder: (context) => Obx(
                      () => Column(
                        mainAxisAlignment: MainAxisAlignment.spaceBetween,
                        children: [
                          Icon(
                            CupertinoIcons.pen,
                            color: this.controller.enablePencil
                                ? Colors.yellow.shade200
                                : Colors.white,
                          ),
                          Text(
                            "画笔",
                            style: TextStyle(
                              color: this.controller.enablePencil
                                  ? Colors.yellow.shade200
                                  : Colors.white,
                              fontSize: 10,
                            ),
                          )
                        ],
                      ),
                    ),
                  ),
                ),
                Container(
                  padding: EdgeInsets.all(10),
                  height: 60,
                  width: 60,
                  child: PopoverButton(
                    onPress: (context) {
                      this.controller.enablePencil = false;
                      this.controller.enableText = true;
                      this.showTextStylePanel(context);
                    },
                    builder: (context) => Obx(
                      () => Column(
                        mainAxisAlignment: MainAxisAlignment.spaceBetween,
                        children: [
                          Icon(
                            CupertinoIcons.text_cursor,
                            color: this.controller.enableText
                                ? Colors.yellow.shade200
                                : Colors.white,
                          ),
                          Text(
                            "文字",
                            style: TextStyle(
                              color: this.controller.enableText
                                  ? Colors.yellow.shade200
                                  : Colors.white,
                              fontSize: 10,
                            ),
                          )
                        ],
                      ),
                    ),
                  ),
                ),
                Container(
                  padding: EdgeInsets.all(10),
                  height: 60,
                  width: 60,
                  child: GestureAvoidDetector(
                    onTap: () {
                      this.controller.removeLastDrawable();
                    },
                    child: Column(
                      mainAxisAlignment: MainAxisAlignment.spaceBetween,
                      children: [
                        Icon(
                          CupertinoIcons.reply_thick_solid,
                          color: Colors.white,
                        ),
                        Text(
                          "后退",
                          style: TextStyle(
                            color: Colors.white,
                            fontSize: 10,
                          ),
                        )
                      ],
                    ),
                  ),
                ),
                Container(
                  padding: EdgeInsets.all(10),
                  height: 60,
                  width: 60,
                  child: GestureAvoidDetector(
                    onTap: () {
                      DialogManager.instance.addDialog(
                        DialogInfo(
                          isDismissible: true,
                          animationType: CLDialogAnimationType.bottom,
                          dialogWidget: () {
                            return SafeArea(
                              top: false,
                              child: Container(
                                height: 120,
                                padding: EdgeInsets.symmetric(horizontal: 10),
                                child: Column(
                                  children: [
                                    GestureAvoidDetector(
                                      onTap: () {
                                        Get.back();
                                        this
                                            .controller
                                            .renderAndDisplayImage(context);
                                      },
                                      child: Container(
                                        decoration: BoxDecoration(
                                          color: Colors.white,
                                          borderRadius:
                                              BorderRadius.circular(8),
                                        ),
                                        height: 54,
                                        child: Center(child: Text("保存")),
                                      ),
                                    ),
                                    SizedBox(
                                      height: 10,
                                    ),
                                    GestureAvoidDetector(
                                      onTap: () => Get.back(),
                                      child: Container(
                                        decoration: BoxDecoration(
                                          color: Colors.white,
                                          borderRadius:
                                              BorderRadius.circular(8),
                                        ),
                                        height: 54,
                                        child: Center(child: Text("取消")),
                                      ),
                                    )
                                  ],
                                ),
                              ),
                            );
                          },
                        ),
                      );
                    },
                    child: Column(
                      mainAxisAlignment: MainAxisAlignment.spaceBetween,
                      children: [
                        Icon(
                          CupertinoIcons.person_2_fill,
                          color: Colors.white,
                        ),
                        Text(
                          "更多",
                          style: TextStyle(
                            color: Colors.white,
                            fontSize: 10,
                          ),
                        )
                      ],
                    ),
                  ),
                )
              ]);
            }

            return Visibility(
              visible: this.controller.showPaint,
              child: SafeArea(
                child: Container(
                  height: 70,
                  color: Color.fromARGB(80, 0, 0, 0),
                  child: Row(
                    mainAxisAlignment: MainAxisAlignment.end,
                    children: actions,
                  ),
                ),
              ),
            );
          }),
        ),
        Align(
          alignment: Alignment.bottomRight,
          child: Obx(
            () => Visibility(
              visible: !this.controller.showPaint,
              child: SafeArea(
                top: false,
                child: GestureAvoidDetector(
                  onTap: () {
                    bool showPaint = !this.controller.showPaint;
                    this.controller.showPaint = showPaint;
                  },
                  child: Container(
                    margin: EdgeInsets.only(right: 20),
                    decoration: BoxDecoration(
                      borderRadius: BorderRadius.circular(8),
                      border: Border.all(
                        width: 1,
                        color: Colors.grey.shade400,
                      ),
                    ),
                    width: 80,
                    height: 80,
                    child: Icon(
                      CupertinoIcons.pencil_slash,
                      size: 44,
                      color: Colors.grey.shade400,
                    ),
                  ),
                ),
              ),
            ),
          ),
        ),
      ],
    );
  }

  Widget paintScreen() {
    return AspectRatio(
      aspectRatio: this.controller.backgroundImage!.width /
          this.controller.backgroundImage!.height,
      child: FlutterPainter(
        controller: this.controller.paintController,
      ),
    );
  }

  @override
  TeacherExplainController initController() {
    return TeacherExplainController();
  }

  @override
  Widget? buildNavigationBar(BuildContext context) {
    return null;
  }

  @override
  List<Widget>? navigationBarLeftActions() {
    return this.controller.showPaint
        ? null
        : [
            GestureAvoidDetector(
              onTap: () {
                Get.back();
              },
              child: Text(
                "\uf053",
                style: TextStyle(
                  fontFamily: IconFont,
                  fontSize: 28.0,
                  color: Colors.white,
                ),
              ),
            ),
          ];
  }

  @override
  List<Widget> navigationBarRightActions() {
    return this.controller.showPaint
        ? [
            CLTextButton(
              title: "收起白板",
              onPressed: () {
                this.controller.showPaint = false;
              },
            )
          ]
        : [
            Container(
              padding: EdgeInsets.only(left: 20),
              width: Get.width - 64,
              child: Row(
                children: [
                  Expanded(
                    flex: 1,
                    child: CLTextButton(
                      title: "原图",
                      onPressed: () {},
                    ),
                  ),
                  Expanded(
                    flex: 1,
                    child: CLTextButton(
                      title: "网格",
                      onPressed: () {},
                    ),
                  ),
                  Expanded(
                    flex: 1,
                    child: CLTextButton(
                      title: "黑白",
                      onPressed: () {},
                    ),
                  ),
                  Expanded(
                    flex: 1,
                    child: CLTextButton(
                      title: "旋转",
                      onPressed: () {},
                    ),
                  ),
                  Expanded(
                    flex: 1,
                    child: CLTextButton(
                      title: "白板",
                      onPressed: () {},
                    ),
                  ),
                ],
              ),
            ),
          ];
  }

  getPens() {
    List<Widget> pens = [
      SizedBox(
        width: 15,
      )
    ];
    for (int i = 0; i < this.controller.pencileSizes.length; i++) {
      double size = this.controller.pencileSizes[i];
      double strokeWidth = this.controller.strokWidths[i];
      pens.add(
        Expanded(
          child: GestureAvoidDetector(
            onTap: () {
              this.controller.strokeWidth = strokeWidth;
            },
            child: Container(
              decoration: BoxDecoration(
                color: this.controller.strokeWidth == strokeWidth
                    ? Colors.grey.shade300
                    : Colors.transparent,
                borderRadius: BorderRadius.circular(4),
              ),
              height: 40,
              child: Icon(
                CupertinoIcons.pencil,
                color: this.controller.strokeColor,
                size: size,
              ),
            ),
          ),
        ),
      );
      pens.add(SizedBox(
        width: 15,
      ));
    }
    return pens;
  }

  getColors() {
    List<Widget> colors = [
      SizedBox(
        width: 10,
      )
    ];
    for (Color color in this.controller.paintColors) {
      colors.add(
        Expanded(
          child: GestureAvoidDetector(
            onTap: () {
              this.controller.strokeColor = color;
              this.controller.textColor = color;
              if (this.controller.enableText) {
                this.controller.addText();
              }
            },
            child: Container(
              height: 32,
              decoration: BoxDecoration(
                color: color,
                borderRadius: BorderRadius.circular(4),
                border: Border.all(
                  width: this.controller.strokeColor == color ? 2 : 0,
                  color: this.controller.strokeColor == color
                      ? Colors.black
                      : Colors.transparent,
                ),
              ),
            ),
          ),
        ),
      );
      colors.add(
        SizedBox(
          width: 10,
        ),
      );
    }
    return colors;
  }

  void showFreeStylePanel(context) {
    showPopover(
      arrowHeight: 15,
      arrowWidth: 30,
      direction: PopoverDirection.bottom,
      context: context,
      bodyBuilder: (content) {
        return Container(
          height: 120,
          width: Get.width - 30,
          color: Colors.white,
          child: Obx(() {
            this.controller.strokeColor;
            this.controller.strokeWidth;
            return Column(
              children: [
                SizedBox(
                  height: 10,
                ),
                Row(children: this.getPens()),
                Divider(),
                SizedBox(
                  height: 10,
                ),
                Row(
                  children: this.getColors(),
                ),
              ],
            );
          }),
        );
      },
    );
  }

  void showTextStylePanel(context) {
    showPopover(
      arrowHeight: 15,
      arrowWidth: 30,
      direction: PopoverDirection.bottom,
      context: context,
      bodyBuilder: (content) {
        return Container(
          height: 60,
          width: Get.width - 30,
          color: Colors.white,
          child: Obx(() {
            this.controller.textColor;
            return Row(
              children: this.getColors(),
            );
          }),
        );
      },
    );
  }
}
